package com.huwaiwai001.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by hww on 2019/1/14 2:58 PM.
 */
public class ThreadTest {

    public static void main(String [] args) throws InterruptedException {
//        testInterrupted();
//        testLockInterruptibly();
        testThreadLocal();
    }

    /**
     * 测试中断线程的方式  针对非阻塞状态的线程 建议使用第三种方式
     * 1.通过interrupt()方法中断阻塞状态的线程
     * 2.通过interrupt() + isInterrupted()方法中断运行状态的线程
     * 3.通过线程内部定义volatile变量 中断线程
     */
    private static void testInterrupted() throws InterruptedException {
        //中断阻塞的线程
        Thread thread = new MySleepThread();
        long start = System.currentTimeMillis();
        thread.start();
        thread.interrupt();
        thread.join();
        System.out.println("case-1 消耗时间 -- " + (System.currentTimeMillis() - start));

        //中断运行状态的线程
        thread = new MyInterruptThread();
        start = System.currentTimeMillis();
        thread.start();
        thread.interrupt();
        thread.join();
        System.out.println("case-2 消耗时间 -- " + (System.currentTimeMillis() - start));

        //通过线程内部变量 中断运行状态的线程
        MyStopFlagThread t1 = new MyStopFlagThread();
        start = System.currentTimeMillis();
        t1.start();
        t1.setStop(true);
        t1.join();
        System.out.println("case-3 消耗时间 -- " + (System.currentTimeMillis() - start));
    }

    /**
     * 通过lockInterruptibly方法获取锁造成的线程阻塞 可以使用interrupt方法中断阻塞状态
     */
    private static void testLockInterruptibly() {
        Lock lock = new ReentrantLock();
        Thread t1 = new MyLockInterruptibleThread(lock);
        Thread t2 = new MyLockInterruptibleThread(lock);
        t1.start();
        t2.start();
        t2.interrupt();
    }

    /**
     * 线程本地变量 实际上是在线程中维护了一个Map 用ThreadLocal对象作为key 值作为value
     */
    private static void testThreadLocal() {
        ThreadLocal<String> strLocal = new ThreadLocal<>();
        ThreadLocal<Integer> intLocal = new ThreadLocal<>();

        strLocal.set("strValue");
        intLocal.set(110);

        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());

    }



}

//会通过sleep方法阻塞5秒
class MySleepThread extends Thread {
    @Override
    public void run() {
        long start = System.currentTimeMillis();
        try {
            System.out.println("开始执行 - " + currentThread().getName());
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            System.out.println("线程中断 - " + currentThread().getName());
        }
        System.out.println("MySleepThread.run执行时间 - " + (System.currentTimeMillis() - start));
    }
}

//可以通过interrupt方法中断运行中的线程
class MyInterruptThread extends Thread {
    @Override
    public void run() {
        long start = System.currentTimeMillis();
        int i = 0;
        while (!isInterrupted() && i < 1) {
        }
        System.out.println("MyInterruptThread.run执行时间 - " + (System.currentTimeMillis() - start));
    }
}

//通过线程内部的标记位中断运行中的线程
class MyStopFlagThread extends Thread {
    private volatile boolean isStop = false;
    @Override
    public void run() {
        long start = System.currentTimeMillis();
        while (!isStop) {
        }
        System.out.println("MyInterruptThread.run执行时间 - " + (System.currentTimeMillis() - start));
    }
    void setStop(boolean stop) {
        this.isStop = stop;
    }
}

class MyLockInterruptibleThread extends Thread {

    private Lock lock;

    MyLockInterruptibleThread(Lock lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {
            System.out.println(name + " - run");
            lock.lockInterruptibly();
            System.out.println(name + " - 获取锁");
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            System.out.println("线程中断 - " + name);
        } finally {
            lock.unlock();
        }
        System.out.println(name + " - 执行完毕");
    }
}